package cn.tedu.ivos.audit.service.impl;

import cn.tedu.ivos.application.mapper.ApplicationMapper;
import cn.tedu.ivos.application.pojo.entity.Application;
import cn.tedu.ivos.audit.mapper.AuditMapper;
import cn.tedu.ivos.audit.pojo.dto.AuditQuery;
import cn.tedu.ivos.audit.pojo.dto.AuditSaveParam;
import cn.tedu.ivos.audit.pojo.entity.Audit;
import cn.tedu.ivos.audit.pojo.vo.AuditVO;
import cn.tedu.ivos.audit.service.AuditService;
import cn.tedu.ivos.base.enums.ApplicationStatusEnum;
import cn.tedu.ivos.base.enums.AuditStatusEnum;
import cn.tedu.ivos.user.mapper.UserMapper;
import cn.tedu.ivos.user.pojo.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringJoiner;

@Slf4j
@Service
@Transactional// 事务性注解 保证数据统一性 原子性 要么一起成功 要么一起失败
public class AuditServiceImpl implements AuditService {
    @Autowired
    AuditMapper auditMapper;
    @Autowired
    UserMapper userMapper;
    @Autowired
    ApplicationMapper applicationMapper;

    @Override
    public void insertAudit(Application application) {
        log.debug("生成新增申请单对应的审批数据业务:application={}", application);
        // 1.获取申请表中的审批人id集合[Xxx,Yyy]
        List<Long> auditUserIdList = application.getAuditUserIdList();
        // 2.遍历审批人id集合 遍历结果元素为多少个 则库中对应生成该集合元素个数的行数的数据 表示由多少个上级进行审核
        for (int i = 0; i < auditUserIdList.size(); i++) {
            Audit audit = new Audit();
            // 3.设置本条审批单的相关数据
            // 3.1 设置申请单id
            audit.setApplicationId(application.getId());
            // 3.2 设置审批人id
            audit.setAuditUserId(auditUserIdList.get(i));
            // 4.设置审批次序 直属领导次序为0 上上级领导次序为1
            audit.setAuditSort(i);
            // 5.设置审批单状态 + 判断
            if (i == 0) {
                // 0表示第1条审批数据 对应的人是直属领导 审批状态为"待我审核"
                audit.setAuditStatus(AuditStatusEnum.MY_PENDING.getCode());
            } else {
                // 1表示第2条审批数据 对应的人是上上级领导 审批状态为"待他人审核"
                audit.setAuditStatus(AuditStatusEnum.PENDING.getCode());
            }
            // 6.设置创建时间
            audit.setCreateTime(new Date());
            // 7.审批数据入库
            auditMapper.insert(audit);
        }
    }

    @Override
    public List<AuditVO> selectAudit(AuditQuery auditQuery) {
        log.debug("查询审批单业务:auditQuery={}", auditQuery);
        // 1.根据条件 查询所有的审批数据
        List<AuditVO> auditVOList = auditMapper.selectAudit(auditQuery);
        /* 申请表与审批表联查 可以查询大部分数据 但是多个审批人姓名数据需要加工才能获取 */
        // 2.遍历 依次获取每一个审批对象
        for (int i = 0; i < auditVOList.size(); i++) {
            AuditVO auditVO = auditVOList.get(i);
            // 3.调用自定义方法 获取审批数据
            assignAuditUserList(auditVO);
        }
        return auditVOList;
    }

    private void assignAuditUserList(AuditVO auditVO) {
        List<String> auditUsernameList = new ArrayList<>();
        ArrayList<Long> auditUserIdList = new ArrayList<>();
        // 查询当前审批单对应的申请单下的所有审批单数据
        List<AuditVO> auditVOList = auditMapper.selectAuditByApplicationId(auditVO.getApplicationId());
        // 依次获取每条审批数据
        for (int i = 0; i < auditVOList.size(); i++) {
            Long userId = auditVOList.get(i).getAuditUserId();
            auditUserIdList.add(userId);
            UserVO user = userMapper.selectById(userId);
            auditUsernameList.add(user.getUsername());
        }
        StringJoiner stringJoiner = new StringJoiner(",");
        for (String username : auditUsernameList) {
            stringJoiner.add(username);
        }
        auditVO.setAuditUserIdList(auditUserIdList);
        auditVO.setAuditUsernameList(stringJoiner.toString());
    }

    @Override
    public void updateAudit(AuditSaveParam auditSaveParam) {
        log.debug("更新审批单业务:auditSaveParam={}", auditSaveParam);
        Audit audit = new Audit();
        BeanUtils.copyProperties(auditSaveParam, audit);
        audit.setUpdateTime(new Date());
        // 准备当前审批单对应的申请单对象
        Application application = new Application();
        application.setId(audit.getApplicationId());
        application.setUpdateTime(new Date());
        // 判断前端传入的审批单操作为"通过"还是"驳回" 分别针对不同的审批结果做后续处理
        if (audit.getAuditStatus().equals(AuditStatusEnum.AUDITED.getCode())) {// "已审批"(审批通过)
            // 更新当前审批单的状态和更新时间
            auditMapper.update(audit);
            /* 继续查询其他审批单: 其他审批单与当前审批单对应的申请单id为同一个 */
            AuditQuery auditQuery = new AuditQuery();
            auditQuery.setApplicationId(auditQuery.getApplicationId());
            // 根据申请单id查询当前申请单对应的所有未审批的审批单总数(注意: 当前审批单已审批通过)
            Integer count = auditMapper.selectRestAuditCount(auditQuery);
            if (count > 0) {// 还有未审批数据
                // 同一申请id下的审批单数据 下一条审批单数据为上一条审批单次序+1(0,1)
                auditQuery.setAuditSort(audit.getAuditSort() + 1);
                // 查询下一条审批单数据(注意: 返回值为List类型 但是只能查询出一条或无数据)
                List<AuditVO> auditVOList = auditMapper.selectAudit(auditQuery);
                // 安全性判断: auditVOList中的数据不为空
                if (auditVOList != null && auditVOList.size() > 0) {
                    AuditVO auditVO = auditVOList.get(0);
                    // 创建空审批对象 用于后续更新数据库
                    Audit audit2 = new Audit();
                    audit2.setId(auditVO.getId());
                    // 设置第二条审批数据的状态为"待我审核"
                    audit2.setAuditStatus(AuditStatusEnum.MY_PENDING.getCode());
                    auditMapper.update(audit2);
                }
                // 设置申请单状态为"审核中"(第一条审核数据的状态已变为"已审核",第二条审批数据还未审批,为"待我审批"状态)
                application.setStatus(ApplicationStatusEnum.AUDIT.getCode());
                applicationMapper.update(application);
            } else {// 无未审批数据
                // 设置申请单状态为"已审核"(后续可进行分配车辆操作)
                application.setStatus(ApplicationStatusEnum.AUDITED.getCode());
                applicationMapper.update(application);
            }
        } else if (audit.getAuditStatus().equals(AuditStatusEnum.REJECT.getCode())) {// "审批驳回"
            auditMapper.update(audit);// 更新当前审批单
            AuditQuery auditQuery = new AuditQuery();
            auditQuery.setApplicationId(audit.getApplicationId());
            // 根据申请单id查询所有的审批单
            List<AuditVO> auditVOList = auditMapper.selectAudit(auditQuery);
            // 判断是否能查询到审批单数据
            if (auditVOList != null && auditVOList.size() > 0) {
                for (int i = 0; i < auditVOList.size(); i++) {
                    AuditVO auditVO = auditVOList.get(i);
                    // 若当前遍历到的审批单状态为"待他人审核" 即未审核 删除
                    if (AuditStatusEnum.PENDING.getCode().equals(auditVO.getAuditStatus())) {
                        auditMapper.deleteById(auditVO.getId());
                    }
                }
            }
            // 设置申请单状态为"已驳回" 并设置驳回原因
            application.setStatus(AuditStatusEnum.REJECT.getCode());
            application.setRejectReason(auditSaveParam.getRejectReason());
            applicationMapper.update(application);
        }
    }
}
